/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.ui.properties.advanced;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertyDescriptor;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.VisibilityKind;

import com.cea.papyrus.core.ui.dialogs.ChooseAggregationKindDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseAssociationDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseDirectionDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseRedefinedPropertiesDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseSubsetPropertiesDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseTypeDialog;
import com.cea.papyrus.core.ui.dialogs.ChooseVisibilityDialog;
import com.cea.papyrus.core.ui.dialogs.LiteralIntegerDialog;
import com.cea.papyrus.core.ui.dialogs.UnlimitedNaturalDialog;
import com.cea.papyrus.core.utils.Debug;

/**
 * 
 */
public class EObjectPropertySource implements IPropertySource {
	
	/**
	 * 
	 */
	private EObject object;
	
	/**
	 * 
	 */
	private int channel=18;
	
	/**
	 * 
	 * 
	 * @param obj 
	 */
	public EObjectPropertySource( EObject obj ) {
		this.object = obj;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	public Object getEditableValue() {
		return object;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	public IPropertyDescriptor[] getPropertyDescriptors() {
		Iterator	it;
		if(object == null) {
			return new IPropertyDescriptor[0];
		}
		EClass		cls = object.eClass();
		ArrayList	descriptors = new ArrayList();
		String categoryDescriptor;
		PropertyDescriptor propertyDescriptor=null;
		
		
		it = cls.getEAllAttributes().iterator();
		Debug.debug(this,"\n---------------object :"+ object+" -----------------------", channel);
		categoryDescriptor=object.eClass().getName()+" property";
		
	
		int maxFeature =object.eClass().getFeatureCount();
		/*
		 * From fetaure of object, the choose dialogbox is selected
		 */
		for (int i=0;i<maxFeature;i++){
			EStructuralFeature es=object.eClass().getEStructuralFeature(i);
			//this a EAttribute
			if (es instanceof EAttribute){
				EAttribute	attr = (EAttribute)es;
				EDataType	type = attr.getEAttributeType();
				
				//the name of the class has to be editable
				if( (type.getInstanceClass() == String.class) && attr.getName().equals("name")) {
					//In this case the qualifiedName haven't to be changed
					propertyDescriptor=new TextPropertyDescriptor(new Integer(i).toString() ,
							object.eClass().getEStructuralFeature(i).getName());
				}
				// this is a boolean
				else if( (type.getInstanceClass() == boolean.class) && attr.isChangeable()) {
					if((object.eClass().getEStructuralFeature(i).getName()).equals("isUnique")){
					}
						propertyDescriptor=new CheckboxPropertyDescriptor(new Integer(i).toString() ,
								object.eClass().getEStructuralFeature(i).getName());
					}
				//this is the visisbility
				else if( type.getInstanceClass() == VisibilityKind.class ) {
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseVisibilityDialog.class,
							(org.eclipse.uml2.uml.Element)object);	
				}
				//this is the aggregation
				else if(type.getInstanceClass() == AggregationKind.class){
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseAggregationKindDialog.class,
							(org.eclipse.uml2.uml.Element)object);
						
				}
				//this is the Direction of the parameter
				else if( type.getInstanceClass() == ParameterDirectionKind.class ) {
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseDirectionDialog.class,
							(org.eclipse.uml2.uml.Element)object);	
				}
				
				//this is a non changeable EAttribute
				else{
//					if(!object.eClass().getEStructuralFeature(i).getName().equals("upper") && (!object.eClass().getEStructuralFeature(i).getName().equals("lower")))
						propertyDescriptor=new PropertyDescriptor( new Integer(i).toString(),
								object.eClass().getEStructuralFeature(i).getName()) ;
				}
				
//				if(propertyDescriptor != null) {
					descriptors.add(propertyDescriptor);
					propertyDescriptor.setCategory(categoryDescriptor);
//				}
			}
			
			// this is e Reference
			else if(es instanceof EReference){
				EReference eRef=(EReference)es;
				Debug.debug(this,"+"+eRef.getName()+"+",channel);
				if(eRef.getName().equals("type")){
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseTypeDialog.class,
							(org.eclipse.uml2.uml.Element)object);
						
				}
			
				else if(eRef.getName().equals("subsettedProperty") &&
						((((Element)object).getOwner()) instanceof org.eclipse.uml2.uml.Class)){
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseSubsetPropertiesDialog.class,
							(org.eclipse.uml2.uml.Element)object);
						
				}
				
				else if(eRef.getName().equals("redefinedProperty") &&
						((((Element)object).getOwner()) instanceof org.eclipse.uml2.uml.Class)){
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseRedefinedPropertiesDialog.class,
							(org.eclipse.uml2.uml.Element)object);
						
				}
				
				else if(eRef.getName().equals("association")){
					propertyDescriptor=new ChoosePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							ChooseAssociationDialog.class,
							(org.eclipse.uml2.uml.Element)object);
						
				}
				
				else if(eRef.getName().equals("lowerValue")){
					propertyDescriptor=new CreateValuePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							LiteralIntegerDialog.class);
						
				}
				else if(eRef.getName().equals("upperValue")){
					propertyDescriptor=new CreateValuePropertyDescriptor(
							new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName(),
							UnlimitedNaturalDialog.class);
						
				} else {
					propertyDescriptor=new PropertyDescriptor( new Integer(i).toString(),
							object.eClass().getEStructuralFeature(i).getName());
				}
				
				
				propertyDescriptor.setLabelProvider(new ReferenceLabelProvider());
				descriptors.add(propertyDescriptor);
				propertyDescriptor.setCategory("References");
			}
			
		}
		return (IPropertyDescriptor[])descriptors.toArray( new IPropertyDescriptor[] {} );
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
	 */
	/**
	 * 
	 * 
	 * @param id 
	 * 
	 * @return 
	 */
	public Object getPropertyValue(Object id) {
		EStructuralFeature	feature = object.eClass().getEStructuralFeature( Integer.parseInt( (String)id ) );
		
		Object result = object.eGet( feature );
		return result != null ? result : "";
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
	 */
	/**
	 * 
	 * 
	 * @param id 
	 * 
	 * @return 
	 */
	public boolean isPropertySet(Object id) {
		// TODO Auto-generated method stub
		return false;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySouce#resetPropertyValue(java.lang.Object)
	 */
	/**
	 * 
	 * 
	 * @param id 
	 */
	public void resetPropertyValue(Object id) {
		// TODO Auto-generated method stub
		
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
	 */
	/**
	 * 
	 * 
	 * @param value 
	 * @param id 
	 */
	public void setPropertyValue(Object id, Object value) {
		EStructuralFeature	feature = object.eClass().getEStructuralFeature( Integer.parseInt( (String)id ) );
		//EObject repositoryObject=Manager.getRessourceManager().lookForUmlElement((NamedElement)object);
		
		Debug.debug(this,"Object modified: "+object+" -> feature:"+feature+" -> value:"+value, channel);
		if (value!=null){
			object.eSet( feature, value );}
		//repositoryObject.eSet( feature, value );
		//Manager.getRessourceManager().dataModified();
	}
	
}
